import numpy as np
import requests
import cv2
import os
from io import BytesIO
from PIL import Image
from app import calculate_angle


def read_image(img_path):
    """
    根据传入的 imgPath 判断是网络地址还是本地地址，然后读取图像。
    :param img_path: 图像路径，可以是本地路径或网络 URL
    :return: numpy.ndarray  对象
    """

    if img_path.startswith(('http://', 'https://')):
        # 设置请求头
        headers = {
            'Referer': 'https://dsc-yygl-hwtest.17mine.cn/',
        }

        # 如果是网络地址
        response = requests.get(img_path, headers=headers)
        response.raise_for_status()  # 确保请求成功
        image = Image.open(BytesIO(response.content)).convert('RGB')
        image = np.array(image)
        # 将 RGB 转换为 BGR
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

    elif os.path.exists(img_path):
        # 如果是本地路径
        image = cv2.imread(img_path)
    else:
        raise ValueError("无效的图像路径或URL")
    return image


def correct_image(image, res):
    """
    根据 YOLO OBB 模型的检测结果 对图像进行校正
    :param image:  需要处理的图片
    :param res:  obb模型检测结果(table 位置)
    :return:   image
    """
    # print(type(image))
    # print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
    # 获取图像的尺寸
    (h_img, w_img) = image.shape[:2]
    table_x, table_y, table_w, table_h, table_angle = parse_obb_res(res)

    print(
        f"table_x (中心点 x 坐标): {table_x.item()},table_y (中心点 y 坐标): {table_y.item()},table_w (宽度): {table_w.item()}, "
        f"table_h (高度): {table_h.item()},table_angle (旋转角度，单位为弧度): {table_angle.item()}")

    # 创建旋转矩阵
    center = (table_x.item(), table_y.item())
    scale = 1.0
    angle_degrees = np.degrees(table_angle.item())
    print(f"旋转角度，单位为度 : {angle_degrees}")
    if angle_degrees > 90:
        angle_degrees = 180 + angle_degrees
    print(f"补偿后旋转角度，单位度：{angle_degrees}")
    rotation_matrix = cv2.getRotationMatrix2D(center, angle_degrees, scale)

    # 计算旋转后的边界框大小
    cos = np.abs(rotation_matrix[0, 0])
    sin = np.abs(rotation_matrix[0, 1])

    new_width = int((h_img * sin) + (w_img * cos))
    new_height = int((h_img * cos) + (w_img * sin))

    # 调整旋转矩阵以考虑新的图像中心
    rotation_matrix[0, 2] += (new_width / 2) - center[0]
    rotation_matrix[1, 2] += (new_height / 2) - center[1]

    # 应用旋转
    rotated_image = cv2.warpAffine(image, rotation_matrix, (new_width, new_height))

    # cv2.imshow('Original Image', image)
    # cv2.imshow('Rotated Image', rotated_image)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()
    # 保存或显示旋转后的图像
    return rotated_image


def correct_image_to_up(image, res1, res2):
    """
    根据 YOLO OBB 模型的检测结果 将图片旋转到向上
    :param res2:  obb模型检测结果(title位置)
    :param image:  需要处理的图片
    :param res1:  obb模型检测结果(table 位置)
    :return:   image
    """
    # print(type(image))
    # print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
    # 获取图像的尺寸
    (h_img, w_img) = image.shape[:2]
    table_x, table_y, table_w, table_h, table_angle = parse_obb_res(res1)
    title_x, title_y, title_w, title_h, title_angle = parse_obb_res(res2)
    print(
        f"table_x (中心点 x 坐标): {table_x.item()},table_y (中心点 y 坐标): {table_y.item()},table_w (宽度): {table_w.item()}, "
        f"table_h (高度): {table_h.item()},table_angle (旋转角度，单位为弧度): {table_angle.item()}")
    print(f"title_x (中心点 x 坐标): {title_x.item()},title_y (中心点 y 坐标): {title_y.item()}")

    # 计算 table 中心点与 title 中心点之间联线与水平方向的夹角 ，因为图片坐标是以左上角为0点，的，因此此处需要将坐标进行调整，以满足以左下角为0点
    horizontal_angle = calculate_angle.calculate_angle(table_x, h_img - table_y, title_x, h_img - title_y)
    print(f"水平方向的夹角: {horizontal_angle}")
    # 显示连线与夹角
    # draw_line(image, table_x, height-table_y, title_x, height-title_y)
    offset = 0
    if 45 <= horizontal_angle <= 135:
        offset = 0
    elif -135 <= horizontal_angle <= -45:
        offset = 180
    elif 135 < horizontal_angle or horizontal_angle < -135:
        offset = 270
    elif -45 < horizontal_angle < 45:
        offset = 90

    # 将   numpy.ndarray   转换为 PIL.JpegImagePlugin.JpegImageFile
    image = Image.fromarray(np.array(image))
    # 旋转图片
    rotated_image = image.rotate(offset, expand=True)
    # cv2.imshow('Original Image', np.array(image))
    # cv2.imshow('Rotated Image', np.array(rotated_image))
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()
    # 保存或显示旋转后的图像

    # 将   PIL.JpegImagePlugin.JpegImageFile 转换成  numpy.ndarray 并返回
    return np.array(rotated_image)


def parse_obb_res(res):
    """
    解析 obb 模型推理的结果
    :param res:
    :return:
    """
    obb = res[0].obb
    a = obb.xywhr.cpu()
    return a[0]
